#通过装饰器实现单例模式
#@语法糖，装饰器本质是闭包函数
def outer(fn):   #class类名作为参数传递给fn
    _ins = {}

    def inner():
        if fn not in _ins:
            _ins[fn] = fn()   # key = value 把fn()值传入到字典，fn:fn()
            print(fn)
            print(_ins)
            print(_ins[fn])
        return _ins[fn]
    return inner

@outer
class A(object): #class类名
    a = 1

a1 = A()
a2 = A()
print(id(a1))
print(id(a2))
print('\n')



#通过导入模块实现单例模式
from test0407 import Test   #从文件“test0407.py”中导入 Test类
from test0407 import Test   #引入多次也只会执行一次
print('\n')
#python文件的模块是天然的单利模式，因为模块第一次导入时会加载到内存空间，
#第二次及以后再导入时，只会引用而不会再次执行模块代码。




#通过元类实现单例模式
'''
hasattr()函数用于判断对象是否包含对应的属性。
参数是一个对象和一个字符串，如果字符串时对象的属性，
函数返回True,否则返回Flase。

'''
class A:
    b = 2
    def test(sefl):
        print('这是test')
#判断是否包含属性b
print(hasattr(A(),'b'))    #True
#判断是否包含test方法
print(hasattr(A(),'test')) #True
print('\n')

'''使用hasattr()来实现单例模式'''

class A1:
    def __init__(self,name):   #初始化实例方法
        self.name = name  #实例属性
    def __new__(cls,*args,**kwargs):
        #ins不存在时执行if内的代码块
        if not hasattr(cls,'ins'):  #hasattr(cls,'ins')为False，代表对象ins不存在，此时该条件not hasattr(cls,'ins')为真，则执行if代码。
            cls.ins = super().__new__(cls) #调用父类new方法创建实例
        return cls.ins

a = A1('张三')
b = A1('李四')
print(id(a))
print(id(b))     #内存地址与a一致，即单例模式
print(a.name)    #李四
print(b.name)    #李四  （因为是单例模式，后面的值会覆盖前面的值）
            




